﻿#include "InpReadInformationMapper.h"
#include "FITK_Component/FITKAbaqusData/FITKDataCase.h"
#include "FITK_Interface/FITKInterfacePhysics/FITKAbstractMaterial.h"
#include "FITK_Interface/FITKInterfacePhysics/FITKAbstractSection.h"
#include "FITK_Interface/FITKInterfaceModel/FITKModelSet.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaAssembly.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaTransform.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaAbstractLoad.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaLoadManager.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaBoundaryConditionManager.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaAbstractBoundaryCondition.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaBoundaryConditionDisplacement.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaBoundaryConditionSymmetry.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaLoadConcentratedForce.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaLoadPressure.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaLoadMoment.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaLoadBodyForce.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaLoadGravity.h"
#include "FITK_Interface/FITKInterfaceModel/FITKComponentManager.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaEngineeringFeature.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaInertiaManager.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaInertiaPointMassInertia.h"
#include "FITK_Component/FITKAbaqusData/FITKAbaqusPart.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaSpringDashpotManager.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaSpringDashpotPoint2Point.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaConnectorAssignment.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaConnectorSection.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaConnectorElement.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaWire.h"

namespace IO
{
    InpReadInformationMapper::InpReadInformationMapper(AbaqusData::FITKDataCase* caseData)
        :_caseData(caseData)
    {
    }

    InpReadInformationMapper::~InpReadInformationMapper()
    {
        for (InpElementDataInfo* data : _elementDataInfo)
        {
            if (!data)continue;
            delete data;
        }
        for (InpOrientationInfo* data : _orientationDataMap)
        {
            if (!data)continue;
            delete data;
        }
        QList<InpConnectorSectionAssignInfo*> infoList = _connAssignSectionMap.values();
        for (InpConnectorSectionAssignInfo* data : infoList)
        {
            if (!data)continue;
            delete data;
        }
    }

    void InpReadInformationMapper::insertSectionDataMaterialName(Interface::FITKAbstractSection* section, QString mat)
    {
        //追加材料
        _materials[section].append(mat);
    }

    void InpReadInformationMapper::insertSetDataTransformName(Interface::FITKModelSet* setData, QString tranformName)
    {
        //追加局部坐标系
        _setTransformMap[setData] = tranformName;
    }

    void InpReadInformationMapper::insertOrientationInfoData(QString name, int csysId, int modelId, QString secondLine)
    {
        InpOrientationInfo* info = new InpOrientationInfo;
        info->_csysId = csysId;
        info->_modelId = modelId;
        info->_secondLine = secondLine;
        //追加Orientation
        _orientationDataMap.insert(name, info);
    }

    QString InpReadInformationMapper::getOrientationSecondLine(QString name, int modelId, int& csysId)
    {
        csysId = 0;
        if (!_orientationDataMap.contains(name))return QString();
        //获取key并查找第二行数据
        QList<InpOrientationInfo*> infoList = _orientationDataMap.values(name);
        for (InpOrientationInfo* info : infoList)
        {
            if (info->_modelId == modelId)
            {
                csysId = info->_csysId;
                return info->_secondLine;
            }
        }
        return QString();
    }

    void InpReadInformationMapper::insertElementInfo(InpElementDataInfo* info)
    {
        //追加Element
        _elementDataInfo.append(info);
    }

    void InpReadInformationMapper::insertConnectorAssignment(Interface::FITKAbaConnectorAssignment* assignData, InpConnectorSectionAssignInfo* info)
    {
        //追加连接器
        _connAssignSectionMap.insert(assignData, info);
    }

    void InpReadInformationMapper::insertElementConnect(int elementId, Interface::FITKAbaAssEleCONN3D2* element)
    {
        //追加连接器单元
        _elementConnect.insert(elementId, element);
    }

    Interface::FITKAbaConnectorSection* InpReadInformationMapper::getConnectorSectionByBehaviorName(QString behaviorName)
    {
        //获取连接器截面数据
        for (QHash<Interface::FITKAbaConnectorAssignment*, InpConnectorSectionAssignInfo*>::const_iterator itr = _connAssignSectionMap.constBegin();
            itr != _connAssignSectionMap.constEnd(); ++itr)
        {
            if (itr.value()->_behavior == behaviorName)
                return itr.value()->_sectionData;
        }
        return nullptr;
    }

    void InpReadInformationMapper::map()
    {
        this->materialSectionMap();
        this->transformSetMap();
        this->elementInertiaMap();
        this->elementSpringDashpotMap();
        this->connectSectionAssignMap();
    }

    void InpReadInformationMapper::materialSectionMap()
    {
        if (_caseData == nullptr) return;
        Interface::FITKMaterialManager* matManger = _caseData->getMaterialManager();
        Interface::FITKAbstractSectionManager* secManger = _caseData->getSectionManager();
        if (matManger == nullptr || secManger == nullptr) return;

        QList<Interface::FITKAbstractSection*> sections = _materials.keys();
        for (Interface::FITKAbstractSection* section : sections)
        {
            //变量section
            if (!secManger->isContains(section)) continue;
            const QStringList materials = _materials.value(section);

            for (int i = 0; i < materials.size(); ++i)
            {
                //查找材料
                const QString matName = materials.at(i);
                Interface::FITKAbstractMaterial* m = matManger->getDataByName(matName);
                if (m == nullptr) continue;
                //建立关联
                section->setMaterial(m, i);
            }
        }
    }

    void InpReadInformationMapper::transformSetMap()
    {
        //错误判断
        if (_caseData == nullptr) return;
        //获取装配数据
        Interface::FITKAbaAssembly* assembly = _caseData->getAssembly();
        if (!assembly)return;
        //获取边界管理器，载荷管理器，局部坐标系管理器
        Interface::FITKAbaBoundaryConditionManager* boundaryManager = _caseData->getBCManager();
        Interface::FITKAbaLoadManager* loadManager = _caseData->getLoadManager();
        Interface::FITKAbaTransformManager* transformManager = assembly->getTransformManager();
        if (!boundaryManager || !loadManager || !transformManager)return;
        //遍历边界设置局部坐标系
        int count = boundaryManager->getDataCount();
        for (int i = 0; i < count; ++i)
        {
            //获取边界数据
            Interface::FITKAbaAbstractBoundaryCondition* boundary = dynamic_cast<Interface::FITKAbaAbstractBoundaryCondition*>(boundaryManager->getDataByIndex(i));
            if (!boundary)continue;
            //获取边界下的集合数据，并获取是否在局部坐标系映射里
            Interface::FITKModelSet* setData = dynamic_cast<Interface::FITKModelSet*>(boundary->getComponentObj());
            if (!setData || !_setTransformMap.contains(setData))continue;
            //获取局部坐标系数据
            Interface::FITKAbaTransform* transform = transformManager->getDataByName(_setTransformMap.value(setData));
            if (!transform)continue;
            int transformId = transform->getDataObjectID();
            //获取边界类型并设置局部坐标系
            Interface::FITKAbaAbstractBoundaryCondition::FITKAbaBoundaryConditionType type = boundary->getBoundaryConditionType();
            if (type == Interface::FITKAbaAbstractBoundaryCondition::FITKAbaBoundaryConditionType::SymmetryAntisymmetryEncastre)
            {
                Interface::FITKAbaBoundaryConditionSymmetry* boundaryData = dynamic_cast<Interface::FITKAbaBoundaryConditionSymmetry*>(boundary);
                if (!boundaryData)continue;
                boundaryData->setCsysId(transformId);
            }
            else if (type == Interface::FITKAbaAbstractBoundaryCondition::FITKAbaBoundaryConditionType::DisplacementRotation)
            {
                Interface::FITKAbaBoundaryConditionDisplacement* boundaryData = dynamic_cast<Interface::FITKAbaBoundaryConditionDisplacement*>(boundary);
                if (!boundaryData)continue;
                boundaryData->setCsysId(transformId);
            }
        }
        //遍历载荷设置局部坐标系
        count = loadManager->getDataCount();
        for (int i = 0; i < count; ++i)
        {
            //获取载荷数据
            Interface::FITKAbaAbstractLoad* load = dynamic_cast<Interface::FITKAbaAbstractLoad*>(loadManager->getDataByIndex(i));
            if (!load)continue;
            //获取载荷下的集合数据，并获取是否在局部坐标系映射里
            Interface::FITKModelSet* setData = dynamic_cast<Interface::FITKModelSet*>(load->getComponentObj());
            if (!setData || !_setTransformMap.contains(setData))continue;
            //获取局部坐标系数据
            Interface::FITKAbaTransform* transform = transformManager->getDataByName(_setTransformMap.value(setData));
            if (!transform)continue;
            int transformId = transform->getDataObjectID();
            //获取载荷类型并设置局部坐标系
            Interface::FITKAbaAbstractLoad::FITKAbaLoadType type = load->getLoadType();
            if (type == Interface::FITKAbaAbstractLoad::FITKAbaLoadType::ConcentratedForce)
            {
                Interface::FITKAbaLoadConcentratedForce* loadData = dynamic_cast<Interface::FITKAbaLoadConcentratedForce*>(load);
                if (!loadData)continue;
                loadData->setCsysId(transformId);
            }
            else if (type == Interface::FITKAbaAbstractLoad::FITKAbaLoadType::Moment)
            {
                Interface::FITKAbaLoadMoment* loadData = dynamic_cast<Interface::FITKAbaLoadMoment*>(load);
                if (!loadData)continue;
                loadData->setCsysId(transformId);
            }
        }
    }

    void InpReadInformationMapper::elementInertiaMap()
    {
        if (_caseData == nullptr) return;
        //获取partManager
        AbaqusData::FITKAbaqusPartManager* partManager = _caseData->getPartManager();
        if (!partManager)return;
        int partCount = partManager->getDataCount();
        for (int i = 0; i < partCount; ++i)
        {
            //获取part
            AbaqusData::FITKAbaqusPart* part = partManager->getDataByIndex(i);
            if (!part)continue;
            //获取part下的工程特性
            Interface::FITKAbaPartEngineeringFeature* engineeringFeaturePart = part->getPartEngineerFeature();
            if (!engineeringFeaturePart)return;
            //获取惯量管理器
            Interface::FITKAbaInertiaManager* inertiaManager = engineeringFeaturePart->getInertiaManager();
            if (!inertiaManager)return;
            for (int j = inertiaManager->getDataCount() - 1; j >= 0; --j)
            {
                Interface::FITKAbaAbstractInertia* inertia = inertiaManager->getDataByIndex(j);
                if (!this->setElementInertia(inertia, part, j))
                    inertiaManager->removeDataObj(inertia);
            }
        }
        //获取装配
        Interface::FITKAbaAssembly* assembly = _caseData->getAssembly();
        if (!assembly)return;
        //获取装配下的工程特性
        Interface::FITKAbaAssemblyEngineeringFeature* engineeringFeatureAssembly = assembly->getAssemblyEngineerFeature();
        if (!engineeringFeatureAssembly)return;
        //获取惯量管理器
        Interface::FITKAbaInertiaManager* inertiaManager = engineeringFeatureAssembly->getInertiaManager();
        if (!inertiaManager)return;
        for (int i = inertiaManager->getDataCount() - 1; i >= 0; --i)
        {
            Interface::FITKAbaAbstractInertia* inertia = inertiaManager->getDataByIndex(i);
            if (!this->setElementInertia(inertia, assembly, i))
                inertiaManager->removeDataObj(inertia);
        }
    }

    void InpReadInformationMapper::elementSpringDashpotMap()
    {
        if (_caseData == nullptr) return;
        //获取装配
        Interface::FITKAbaAssembly* assembly = _caseData->getAssembly();
        if (!assembly)return;
        //获取装配下的工程特性
        Interface::FITKAbaAssemblyEngineeringFeature* engineeringFeatureAssembly = assembly->getAssemblyEngineerFeature();
        if (!engineeringFeatureAssembly)return;
        //获取弹簧管理器
        Interface::FITKAbaSpringDashpotManager* springDashManager = engineeringFeatureAssembly->getSpringDashManager();
        if (!springDashManager)return;
        for (int i = springDashManager->getDataCount() - 1; i >= 0; --i)
        {
            //获取弹簧数据
            Interface::FITKAbaAbstractSpringDashpot* data = springDashManager->getDataByIndex(i);
            if (!this->setElementSpringDashpot(data, assembly))
                springDashManager->removeDataObj(data);
        }
    }

    void InpReadInformationMapper::connectSectionAssignMap()
    {
        if (_caseData == nullptr) return;
        //获取装配
        Interface::FITKAbaAssembly* assemblyData = _caseData->getAssembly();
        if (!assemblyData)return;
        //获取集合管理器和坐标系管理器
        Interface::FITKComponentManager* setSurfManager = assemblyData->getComponentManager();
        Interface::FITKAbaTransformManager* transformManager = assemblyData->getTransformManager();
        if (!setSurfManager || !transformManager)return;
        //连接器映射展开并设置数据
        QList<Interface::FITKAbaConnectorAssignment*> assignConnectList = _connAssignSectionMap.keys();
        for (Interface::FITKAbaConnectorAssignment* assignData : assignConnectList)
        {
            InpConnectorSectionAssignInfo* info = _connAssignSectionMap.value(assignData);
            if (!info || !info->_sectionData)continue;
            //连接器指派器设置模型和截面
            Interface::FITKModelSet* setData = dynamic_cast<Interface::FITKModelSet*>(setSurfManager->getDataByName(info->_elset));
            if (!this->connectSetElementIdRevise(setData))continue;
            assignData->assign(setData->getDataObjectID(), info->_sectionData->getDataObjectID());
            //连接器指派器设置坐标系1
            if (!info->_csysName1.isEmpty())
            {
                Interface::FITKAbaTransform* transformData = dynamic_cast<Interface::FITKAbaTransform*>(transformManager->getDataByName(info->_csysName1));
                if (!transformData)continue;
                assignData->setCsysId1(transformData->getDataObjectID());
            }
            //连接器指派器设置坐标系2
            if (!info->_csysName2.isEmpty())
            {
                Interface::FITKAbaTransform* transformData2 = dynamic_cast<Interface::FITKAbaTransform*>(transformManager->getDataByName(info->_csysName2));
                if (!transformData2)continue;
                assignData->setCsysId1(transformData2->getDataObjectID());
            }
        }
    }

    bool InpReadInformationMapper::connectSetElementIdRevise(Interface::FITKModelSet* setData)
    {
        if (!setData) return false;
        //获取集合
        QList<Interface::FITKModelSet*> setList;
        setData->getAbsoluteSet(setList, Interface::FITKModelEnum::FITKModelSetType::FMSElem);
        //重新设置单元id
        for (Interface::FITKModelSet* set : setList)
        {
            if (!set)continue;
            QList<int> elementIdList = set->getAbsoluteMember();
            QList<int> newElemIdList;
            for (int id : elementIdList)
            {
                if (!_elementConnect.contains(id))return false;
                Interface::FITKAbaAssEleCONN3D2* element = _elementConnect.value(id);
                if (!element)return false;
                int newId = element->getElementID();
                newElemIdList.append(newId);
            }
            set->setAbsoluteMember(newElemIdList);
        }
        return true;
    }

    bool InpReadInformationMapper::setElementSpringDashpot(Interface::FITKAbaAbstractSpringDashpot* data, Interface::FITKAbstractModel* model)
    {
        if (_caseData == nullptr || !data || !model) return false;
        QString elsetName = data->getDataObjectName();
        //获取moxingId
        int modelId = model->getDataObjectID();
        //查找对应信息
        InpElementDataInfo* infoData = nullptr;
        for (InpElementDataInfo* info : _elementDataInfo)
        {
            if (info->_elesetName == elsetName && info->_modelId == modelId && this->compareSpringDashpotTypeData(info->_elementType, data))
            {
                infoData = info;
                break;
            }
        }
        if (!infoData)return false;
        //插入点数据
        for (ElementPointInfo info : infoData->_elementMap)
        {
            int num = 0;
            Interface::FITKAbaAssEle3D2* element = new Interface::FITKAbaAssEleSpringDashpot;
            for (QPair<int, int> pointData : info._elementPointData)
            {
                ++num;
                int modelId = pointData.first;
                int pointId = pointData.second;
                if (num == 1)
                    element->setNode1(modelId, pointId);
                else if (num == 2)
                    element->setNode2(modelId, pointId);
            }
            data->appendDataObj(element);
        }
        return true;
    }

    bool InpReadInformationMapper::compareSpringDashpotTypeData(QString type, Interface::FITKAbaAbstractSpringDashpot* data)
    {
        if (!data)return false;
        //类型
        Interface::FITKAbaAbstractSpringDashpot::SpringDashpotType typeData = data->getSpringDashpotType();
        if (typeData == Interface::FITKAbaAbstractSpringDashpot::SpringDashpotType::ConnectTwoPoints)
        {
            //类型是否时指定方向 -是：type=Spring2/Dashpot2 否：type=SpringA/DashpotA
            QString typeStr = "a";
            if (data->getStiffnessState())
            {
                if (type.toLower() == "spring" + typeStr)
                    return true;
            }
            if (data->getDaspotState())
            {
                if (type.toLower() == "dashpot" + typeStr)
                    return true;
            }
        }
        return false;
    }

    bool InpReadInformationMapper::setElementInertia(Interface::FITKAbaAbstractInertia* inertia, Interface::FITKAbstractModel* model, int index)
    {
        if (_caseData == nullptr || !inertia || !model) return false;
        QString elsetName = inertia->getDataObjectName();
        //获取moxingId
        int modelId = model->getDataObjectID();
        //查找对应信息
        InpElementDataInfo* infoData = nullptr;
        for (InpElementDataInfo* info : _elementDataInfo)
        {
            if (info->_elesetName == elsetName && info->_modelId == modelId && this->compareInertiaTypeData(info->_elementType, inertia))
            {
                infoData = info;
                break;
            }
        }
        if (!infoData)return false;
        //获取集合管理器
        Interface::FITKComponentManager* setSurfManager = nullptr;
        if (model->getAbsModelType() == Interface::FITKModelEnum::AbsModelType::AMTMIX)
        {
            //part
            AbaqusData::FITKAbaqusPart* partData = dynamic_cast<AbaqusData::FITKAbaqusPart*>(model);
            if (!partData)return false;
            setSurfManager = partData->getComponentManager();
        }
        else if (model->getAbsModelType() == Interface::FITKModelEnum::AbsModelType::Assembly)
        {
            //assembly
            Interface::FITKAbaAssembly* assemblyData = dynamic_cast<Interface::FITKAbaAssembly*>(model);
            if (!assemblyData)return false;
            setSurfManager = assemblyData->getComponentManager();
        }
        if (!setSurfManager)return false;
        //获取最新名称
        QString setName = setSurfManager->checkName("Set-1");
        //获取set所需的信息
        QHash<int, QList<int>> instandSetList;
        for (ElementPointInfo info : infoData->_elementMap)
        {
            for (QPair<int, int> pointData : info._elementPointData)
            {
                if (instandSetList.contains(pointData.first))
                    instandSetList[pointData.first].append(pointData.second);
                else
                    instandSetList.insert(pointData.first, QList<int>() << pointData.second);
            }
        }
        if (instandSetList.isEmpty())return false;
        //创建set
        QList<int> instanIdList = instandSetList.keys();
        for (int instanceId : instanIdList)
        {
            Interface::FITKModelSet* set = new Interface::FITKModelSet(Interface::FITKModelEnum::FITKModelSetType::FMSNode);
            if (!set)return false;
            //获取编号
            QList<int> memberList = instandSetList.value(instanceId);
            //从小到大排序
            std::sort(memberList.begin(), memberList.end());
            //设置名称
            set->setDataObjectName(setName);
            //设置模型
            set->setModel(instanceId);
            //设置数据
            set->setAbsoluteMember(memberList);
            //插入管理器
            setSurfManager->appendDataObj(set);
        }
        //设置数据参数
        auto setData = setSurfManager->getDataByName(setName);
        if (!setData)return false;
        int setId = setData->getDataObjectID();
        modelId = setData->getAbsModelID();
        inertia->setComponent(setId);
        inertia->setModel(modelId);
        inertia->setDataObjectName(QString("Inertia-%1").arg(index + 1));
        return true;
    }

    bool InpReadInformationMapper::compareInertiaTypeData(QString type, Interface::FITKAbaAbstractInertia* inertia)
    {
        //类型判断
        if (type.toLower() == "mass" || type.toLower() == "rotaryi")
        {
            Interface::FITKAbaInertiaPointMassInertia* pointMassInertia = dynamic_cast<Interface::FITKAbaInertiaPointMassInertia*>(inertia);
            if (!pointMassInertia)return false;
            //质量点
            if (type.toLower() == "mass")
            {
                if (pointMassInertia->getMassType() ==
                    Interface::FITKAbaInertiaPointMassInertia::MassType::Isotropic)
                {
                    if (fabs(pointMassInertia->getIsoTropicMass()) > 1e-16)
                        return true;
                }
                else if (pointMassInertia->getMassType() ==
                    Interface::FITKAbaInertiaPointMassInertia::MassType::Anisotropic)
                {
                    if (fabs(pointMassInertia->getM11()) > 1e-16 || fabs(pointMassInertia->getM22()) > 1e-16 || fabs(pointMassInertia->getM33()) > 1e-16)
                        return true;
                }
            }
            //转动惯量
            else if (type.toLower() == "rotaryi")
            {
                if (fabs(pointMassInertia->getI11()) > 1e-16 || fabs(pointMassInertia->getI22()) > 1e-16 || fabs(pointMassInertia->getI33()) > 1e-16)
                    return true;
                if (pointMassInertia->getSpecifyOffDiagnalTerms())
                {
                    if (fabs(pointMassInertia->getI12()) > 1e-16 || fabs(pointMassInertia->getI13()) > 1e-16 || fabs(pointMassInertia->getI23()) > 1e-16)
                        return true;
                }
            }
        }
        return false;
    }
}
